package com.graduation.project.service.topic.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.graduation.project.entity.dto.task.SaveOrUpdateTaskDTO;
import com.graduation.project.entity.dto.task.ListTaskDTO;
import com.graduation.project.entity.dto.UpdateStatusDTO;
import com.graduation.project.entity.other.LoginUser;
import com.graduation.project.entity.po.Task;
import com.graduation.project.entity.vo.task.ListTaskVO;
import com.graduation.project.entity.vo.task.TaskDetailsVO;
import com.graduation.project.enums.ResultCodeEnum;
import com.graduation.project.mapper.topic.ListTaskMapper;
import com.graduation.project.mapper.topic.TaskMapper;
import com.graduation.project.service.topic.TaskService;
import com.graduation.project.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private ListTaskMapper listTaskMapper;

    @Override
    public ResultUtil<?> listAdviserData() {
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, taskMapper.listAdviserData());
    }

    @Override
    public ResultUtil<?> getTaskDetails(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>().eq(Task::getId, id));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "查询课题不存在");
        }
        TaskDetailsVO output = new TaskDetailsVO();
        BeanUtil.copyProperties(task, output);
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, output);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> addTask(SaveOrUpdateTaskDTO input) {
        // 判断课题名称是否已存在
        LambdaQueryWrapper<Task> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Task::getTaskName, input.getTaskName());
        if (ObjectUtil.isNotEmpty(taskMapper.selectList(lambdaQueryWrapper))) {
            throw new RuntimeException("课题名称已存在");
        }

        Task task = new Task();
        BeanUtil.copyProperties(input, task);
        try {
            taskMapper.insert(task);
        }catch (Exception e) {
            throw new RuntimeException("新增失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "新增成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateTask(SaveOrUpdateTaskDTO input) {
        if (ObjectUtil.isEmpty(input.getId())) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断修改数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, input.getId()));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "修改数据不存在");
        }
        // 只能修改待提交的课题
        if (task.getAuditStatus() != 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "只能修改待提交的课题");
        }
        // 如果修改了课题名称，判断数据库中课题名称是否已存在
        if (!task.getTaskName().equals(input.getTaskName())) {
            LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Task::getTaskName, input.getTaskName())
                    .ne(Task::getId, input.getId());
            if (ObjectUtil.isNotEmpty(taskMapper.selectList(queryWrapper))) {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题名称已存在");
            }
        }
        BeanUtil.copyProperties(input, task);
        // 重置系主任、副院长审核状态/审核意见
        task.setDirectorAuditStatus(0);
        task.setDirectorAuditIdea("");
        task.setSubdecanalAuditStatus(0);
        task.setSubdecanalAuditIdea("");
        try {
            taskMapper.updateById(task);
        }catch (Exception e) {
            throw new RuntimeException("修改失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "修改成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> directorAuditTask(UpdateStatusDTO input) {
        // 判断审核数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, input.getId()));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "审核数据不存在");
        }
        // 判断课题是否是未审核状态
        if (task.getDirectorAuditStatus() != 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "此课题已经审核过啦");
        }
        // 系主任审核状态
        task.setDirectorAuditStatus(input.getStatus());
        // 系主任审核意见
        task.setDirectorAuditIdea(input.getIdea());
        try {
            taskMapper.updateById(task);
        }catch (Exception e) {
            throw new RuntimeException("审核失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "审核成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> subdecanalAuditTask(UpdateStatusDTO input) {
        // 判断审核数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, input.getId()));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "审核数据不存在");
        }
        // 判断系主任是否审核
        if (task.getDirectorAuditStatus() == 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "等待系主任审核");
        }
        // 判断课题是否是未审核状态
        if (task.getSubdecanalAuditStatus() != 0) {
            throw new RuntimeException("此课题已经审核过啦");
        }
        // 副院长审核状态
        task.setSubdecanalAuditStatus(input.getStatus());
        // 副院长审核意见
        task.setSubdecanalAuditIdea(input.getIdea());
        try {
            taskMapper.updateById(task);
        }catch (Exception e) {
            throw new RuntimeException("审核失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "审核成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> deleteTask(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断删除数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, id));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "操作数据不存在");
        }
        // 如果课题已被学生选择，则不能删除
        if (StringUtils.isNotBlank(task.getProposerCode())) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题已被学生选择，不能删除");
        }
        try {
            taskMapper.deleteById(task);
        }catch (Exception e) {
            throw new RuntimeException("删除失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "删除成功");
    }

    @Override
    public ResultUtil<?> listTaskByCondition(ListTaskDTO input) {
        IPage<ListTaskVO> page = new Page<>();
        page.setCurrent(input.getCurrentPage());
        page.setSize(input.getPageSize());

        IPage<ListTaskVO> data = listTaskMapper.listTaskByCondition(page, input);

        Map<String, Object> map = new HashMap<>();
        map.put("listTaskVo", data.getRecords());
        map.put("total", data.getTotal());
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "查询成功", map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> chooseTask(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断课题是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, id));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "选择课题数据不存在");
        }
        // 判断课题是否已通过系主任、副院长审核
        if (task.getDirectorAuditStatus() != 1 || task.getSubdecanalAuditStatus() != 1) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题暂未通过审核");
        }
        // 判断课题是否已经被选择
        if (ObjectUtil.isNotEmpty(task.getProposerCode()) || task.getAuditStatus() != 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题已被选择");
        }
        // 获取用户账号
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authenticationToken.getPrincipal();
        String userCode = loginUser.getUser().getUserCode();
        // 修改课题申请人信息
        task.setProposerCode(userCode);
        task.setAuditStatus(1);
        try {
            taskMapper.updateById(task);
        }catch (Exception e) {
            throw new RuntimeException("选题失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "选题成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> teacherAuditTask(UpdateStatusDTO input) {
        // 判断审核数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, input.getId()));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "审核数据不存在");
        }
        // 判断课题是否已通过系主任、副院长审核
        if (task.getDirectorAuditStatus() != 1 || task.getSubdecanalAuditStatus() != 1) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题暂未通过审核");
        }
        // 判断课题是否被选择
        if (ObjectUtil.isEmpty(task.getProposerCode()) || task.getAuditStatus() == 0) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题未被选择");
        }
        // 判断课题是否是待审核状态
        if (task.getAuditStatus() != 1) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "课题未提交或已被审核");
        }
        // 教师审核状态
        task.setAuditStatus(input.getStatus());
        // 教师审核意见
        task.setAuditIdea(input.getIdea());
        try {
            taskMapper.updateById(task);
        }catch (Exception e) {
            throw new RuntimeException("审核失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "审核成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> cancelChooseTask(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断数据是否存在
        Task task = taskMapper.selectOne(new LambdaQueryWrapper<Task>()
                .eq(Task::getId, id));
        if (ObjectUtil.isEmpty(task)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "数据不存在");
        }
        // 如果选题已通过教师审核，则不能取消选题
        if (task.getAuditStatus() == 2) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "选题已通过审核不能随意取消");
        }
        // 清空选题人信息
        task.setProposerCode("");
        // 重置课题状态为待提交
        task.setAuditStatus(0);
        try {
            taskMapper.updateById(task);
        } catch (Exception e) {
            throw new RuntimeException("操作失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "操作成功");
    }
}
